package props

import (
	"gitee.com/night-tc/gobige/common"
	"gitee.com/night-tc/gobige/logger"
	"gitee.com/night-tc/gobige/msgdef/protomsg"
)

// IProps Entity属性相关的操作
type IProps interface {
	SetProp(index uint32, value interface{})
	PropDirty(index uint32)
	IsDirty(index uint32, dType EDPSorterType) bool
	PropDirty2(index uint32, dType EDPSorterType)
	GetProp(index uint32) interface{}
	//尝试获取属性，如果没有拿到就返回错误
	TryGetProp(index uint32) (interface{}, error)
	GetPropRawByName(name string) IProp
	GetPropRaw(index uint32) IProp
	// 从同步消息中获取数据
	ReadSyncProps(li []*protomsg.SyncProp)
}

/*
属性管理器
可以管理属性的脏字段
*/
type PropDirtyMgr struct {
	def *Def //从文件加载进来的信息
	// 这二个字段是互斥的，只会有一个生效
	sTyp   uint32 //服务器类型如果是0就忽略
	subTye string //子类型名如果为空，表示是主类型

	PropList   map[uint32]IProp    //所有字段按ID查
	PropByName map[string]IProp    //所有字段按名字查
	sorters    []IPropsDirtySorter //标脏分流器
}

func NewPropDirtyMgr() (result *PropDirtyMgr) {
	result = new(PropDirtyMgr)
	result.PropList = make(map[uint32]IProp)
	result.PropByName = make(map[string]IProp)
	result.sorters = make([]IPropsDirtySorter, 0, 2)
	return result
}

func (this *PropDirtyMgr) InitProp(def *Def) {
	this.def = def
}

// 设置属性为指定子类型
func (this *PropDirtyMgr) SetSubType(subType string) {
	this.subTye = subType
}

// 设置属性为指定服务器类型
func (this *PropDirtyMgr) SetSrvType(srvType uint32) {
	this.sTyp = srvType
}

// 获取字段
func (this *PropDirtyMgr) getField(index uint32) (result *FieldDef) {
	result = this.def.FieldsByID[index]
	return
}

// 设置属性
func (this *PropDirtyMgr) setProp(prop IProp) {
	//检查配置表与生成的代码是不是一样的
	if this.sTyp != 0 {
		if common.ArrayIndexof(prop.GetField().WatchSrvs, this.sTyp) == -1 {
			logger.Fatalf("%s setProp %s not is SrvType %d", this.def.Name, prop.GetName(), this.sTyp)
		}
	} else if this.subTye != "" {
		if _, ok := prop.GetField().SubTypes[this.subTye]; !ok {
			logger.Fatalf("%s setProp %s not is subtype %s", this.def.Name, prop.GetName(), this.subTye)
		}
	}
	this.PropByName[prop.GetName()] = prop
	this.PropList[prop.GetIndex()] = prop
}

func (this *PropDirtyMgr) SetProp(index uint32, value interface{}) {
	pmd := this.PropList[index]
	pmd.SetValue(value)
}

func (this *PropDirtyMgr) PropDirty(index uint32) {
	pmd := this.PropList[index]
	for _, sorter := range this.sorters {
		sorter.FlagDirty(pmd)
	}
}
func (this *PropDirtyMgr) IsDirty(index uint32, dType EDPSorterType) bool {
	pmd := this.PropList[index]
	switch dType {
	case EDPSorterTypeSync:
		return pmd.IsSyncDirty()
	case EDPSorterTypeSave:
		return pmd.IsSaveDirty()
	default:
		logger.Error("IsDirty default error. index ", index)
		return false
	}
}

func (this *PropDirtyMgr) PropDirty2(index uint32, dType EDPSorterType) {
	pmd := this.PropList[index]
	for _, sorter := range this.sorters {
		if sorter.GetSorterType() == dType {
			sorter.FlagDirty(pmd)
			break
		}
	}
}
func (this *PropDirtyMgr) GetProp(index uint32) interface{} {
	pmd := this.PropList[index]
	return pmd.GetValue()
}

// 尝试获取属性，如果没有拿到就返回错误
func (this *PropDirtyMgr) TryGetProp(index uint32) (interface{}, error) {
	pmd, ok := this.PropList[index]
	if !ok {
		return nil, ErrProp_NotExist
	}
	return pmd.GetValue(), nil
}

func (this *PropDirtyMgr) GetPropRawByName(name string) IProp {
	pmd, ok := this.PropByName[name]
	if !ok {
		logger.Error("GetPropRawByName error. ", name)
		return nil
	}
	return pmd
}

func (this *PropDirtyMgr) GetPropRaw(index uint32) IProp {
	pmd, ok := this.PropList[index]
	if !ok {
		logger.Error("GetPropRaw error. ", index)
		return nil
	}
	return pmd
}

////////////////////////////////////////////////////////////////

func (this *PropDirtyMgr) ForEachProp(callBack func(p IProp)) {
	for _, p := range this.PropList {
		callBack(p)
	}
}

////////////////////////////////
/* 本包方法 */

// 标记此字段脏
func (this *PropDirtyMgr) setPropDirty(p IProp) {
	for _, sorter := range this.sorters {
		sorter.FlagDirty(p)
	}
}

// 标记此字段脏
func (this *PropDirtyMgr) setPropDirty2(p IProp, dType EDPSorterType) {
	for _, sorter := range this.sorters {
		if sorter.GetSorterType() == dType {
			sorter.FlagDirty(p)
			return
		}
	}
}

// //////////////////////////////
// 属性脏分流器操作
func (e *PropDirtyMgr) GetDirtyPropSorter(sorterType EDPSorterType) IPropsDirtySorter {
	for _, sorter := range e.sorters {
		if sorter.GetSorterType() == sorterType {
			return sorter
		}
	}

	return nil
}

// 设置或替换分流器
func (e *PropDirtyMgr) SetSorter(stype EDPSorterType, sorternew IPropsDirtySorter) {
	for i, sorter := range e.sorters {
		if sorter.GetSorterType() == stype {
			e.sorters[i] = sorternew
			return
		}
	}
	e.sorters = append(e.sorters, sorternew)
}

// 添加分流器
func (e *PropDirtyMgr) AddSorter(sorterType EDPSorterType) {
	for _, sorter := range e.sorters {
		if sorter.GetSorterType() == sorterType {
			return
		}
	}
	if v := NewPropsDirtySorter(sorterType); v != nil {
		e.sorters = append(e.sorters, v)
	}
}

// 删除分流器
func (e *PropDirtyMgr) DelSorter(sorterType EDPSorterType) {
	for i, sorter := range e.sorters {
		if sorter.GetSorterType() == sorterType {
			e.sorters = append(e.sorters[:i], e.sorters[i+1:]...)
		}
	}

}

// 按类型遍历脏数据
func (e *PropDirtyMgr) HandlerSorterResultForeach(sorterType EDPSorterType, consumeFunc func(p IProp)) bool {
	if sorter := e.GetDirtyPropSorter(sorterType); sorter != nil {
		sorter.HandlerForEach(consumeFunc)
		return true
	}

	return false
}

// 按类型获取脏数据列表回调
func (e *PropDirtyMgr) HandlerSorterResult(sorterType EDPSorterType, consumeFunc func([]IProp) bool) bool {
	if sorter := e.GetDirtyPropSorter(sorterType); sorter != nil {
		sorter.HandlerAllList(consumeFunc)
		return true
	}

	return false
}

//属性脏分流器操作
////////////////////////////////
